# -*- coding: utf-8 -*-
## This code is responsable for creating keyframe animation structure.
## Master Research:         Elisabete Thomaselli Nogueira
## Professor:               Claudio Esperanca
## Graduate Student:	    Victor Soares Bursztyn
## Created in: 13-02-08
## Last updated in: 
from scipy import *
from keyframe import *

class Animation:
    """Represents keyframed animations of 3d objects."""
    def __init__(self, keys):
        """Constructor.
        @param keys: a list of objects of type keyframe."""
        self.keys = keys[:]
        self.keys.sort(cmp=lambda a,b: a.frameno-b.frameno)
        self.mult = 1
         
    def interpolate(self,nframes,firstframe=0):
        """Prepares the interpolation from the keys.
        @param nframes: the number of frames to be interpolated.
        @param firstframe: the first frame to be interpolated."""
        
        def makearrays (coord):
            """Utility function to transpose a list of points into a 
            a list of coordinate arrays. Thus, for instance, 
            makearrays([[1,2],[3,4],[5,6]]) returns 
            [array([1,3,5]),array([2,4,6])]"""
            result = []
            for i in range(len(coord[0])):
               result.append(array(map(lambda x:x[i], coord)))
            return result
            
        # Collect the various types of keyframe values into lists
        trans = [] ; ut = []
        rot = [] ;   ur = []
        scale = [] ; us = []
        for k in self.keys:
            if k.translation is not KeyFrame.translation:
               trans.append (k.translation)
               ut.append (k.frameno)
            if k.rotation is not KeyFrame.rotation:
               rot.append (k.rotation)
               ur.append (k.frameno)
            if k.scale is not KeyFrame.scale:
               scale.append (k.scale)
               ur.append (k.scale)
        
        # Create the desired frame range
        self.firstframe = firstframe
        self.nframes = nframes
        frange = arange(firstframe,firstframe+nframes,1)
        
        # Use scipy's interpolating splines to interpolate the various values
        if len(ut)<=1: trans = [(0,0,0),(0,0,0)] ; ut = [0,1]
        spline,u = interpolate.splprep(makearrays(trans),s=0,k=min(3,len(ut)-1),u=array(ut))     
        self.interptrans = interpolate.splev(frange,spline)
        #print "self.interptrans ", self.interptrans

        if len(ur)<=1: rot = [(0,0,1,0),(0,0,1,0)] ; ur = [0,1]
        spline,u = interpolate.splprep(makearrays(rot),s=0,k=min(3,len(ur)-1),u=array(ur))     
        self.interprotate = interpolate.splev(frange,spline)
        
        if len(us)<=1: scale = [(1,1,1),(1,1,1)] ; us = [0,1]
        spline,u = interpolate.splprep(makearrays(scale),s=0,k=min(3,len(us)-1),u=array(us))     
        self.interpscale = interpolate.splev(frange,spline)

        return self.interptrans ## Get translation  moviments to put in a graph
    
    def updateObject (self, frame, obj, sceneElements):
        """Updates an object with the animation parameters for a given frame
        @param frame: animation frame number
        @param obj: object to be updated
        """
        print "frame, self.firstframe, self.nframes ",frame, self.firstframe, self.nframes
        assert (frame >= self.firstframe and frame < self.firstframe+self.nframes)

        self.sceneElements = sceneElements

        i = frame - self.firstframe

        ## Fazer as operacoes com o objeto de indice self.index_m
        """
        if self.selectedModel != -1:
           index_m, index_g = self.findSelections()
           if self.selectedGroup != -1:
              self.sceneElements[index_m].groups[index_g].setTranslate(0, 0, self.tz)
              self.sceneElements[index_m].groups[index_g].box = self.sceneElements[index_m].groups[index_g].box.transform(self.sceneElements[index_m].groups[index_g].getTransformationMatrix())
           else:
              self.sceneElements[index_m].setTranslate(0, 0, self.tz)
              self.sceneElements[index_m].box = self.sceneElements[index_m].box.transform(self.sceneElements[index_m].getTransformationMatrix())   	
           self.update()
        """
               
        self.sceneElements[-1].setTranslate (self.interptrans[0][i],
                          self.interptrans[1][i],
                          self.interptrans[2][i])
        self.sceneElements[-1].setRotate (self.interprotate[0][i],
                       self.interprotate[1][i],
                       self.interprotate[2][i])
        ##               self.interprotate[2][i],
        ##               self.interprotate[3][i])
        self.sceneElements[-1].setScale (self.interpscale[0][i],
                      self.interpscale[1][i],
                      self.interpscale[2][i])
    def printFrame(self, frame):
        """Prints parameters for the given frame
        @param frame: number of frame to print"""
        
        i = frame - self.firstframe
        print "Scale", self.interpscale[0][i],self.interpscale[1][i],self.interpscale[2][i]
        print "Rotate", self.interprotate[0][i],self.interprotate[1][i],self.interprotate[2][i],self.interprotate[3][i]
        print "Translate", self.interptrans[0][i],self.interptrans[1][i],self.interptrans[2][i]   
             

